[MINIOS]Events handling cleaned up. The interface extended to provide
authorkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Wed, 5 Jul 2006 10:27:58 +0000 (11:27 +0100)
committerkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Wed, 5 Jul 2006 10:27:58 +0000 (11:27 +0100)
void* pointer to handlers.
Signed-off-by: Steven Smith <sos22@cam.ac.uk>
Signed-off-by: Grzegorz Milos <gm281@cam.ac.uk>
extras/mini-os/console/xencons_ring.c
extras/mini-os/events.c
extras/mini-os/include/events.h
extras/mini-os/include/lib.h
extras/mini-os/lib/string.c
extras/mini-os/time.c
extras/mini-os/xenbus/xenbus.c

index ff1bf519df94aef1be901573ad417842683efef8..7693235ff083b765e4e92e8958d5e04c67655c92 100644 (file)
@@ -53,7 +53,7 @@ int xencons_ring_send(const char *data, unsigned len)
 
 
 
-static void handle_input(int port, struct pt_regs *regs)
+static void handle_input(int port, struct pt_regs *regs, void *ign)
 {
        struct xencons_interface *intf = xencons_interface();
        XENCONS_RING_IDX cons, prod;
@@ -83,7 +83,8 @@ int xencons_ring_init(void)
        if (!start_info.console_evtchn)
                return 0;
 
-       err = bind_evtchn(start_info.console_evtchn, handle_input);
+       err = bind_evtchn(start_info.console_evtchn, handle_input,
+                         NULL);
        if (err <= 0) {
                printk("XEN console request chn bind failed %i\n", err);
                return err;
index 2aa5349b37df92cbe6e4beb1a53fd539892cb564..0acacb25277c388e7ba0aff3f69ebaa5e28eb16b 100644 (file)
 #include <events.h>
 #include <lib.h>
 
+#define NR_EVS 1024
+
+/* this represents a event handler. Chaining or sharing is not allowed */
+typedef struct _ev_action_t {
+       void (*handler)(int, struct pt_regs *, void *);
+       void *data;
+    u32 count;
+} ev_action_t;
+
 
 static ev_action_t ev_actions[NR_EVS];
-void default_handler(int port, struct pt_regs *regs);
+void default_handler(int port, struct pt_regs *regs, void *data);
 
 
 /*
@@ -35,42 +44,33 @@ int do_event(u32 port, struct pt_regs *regs)
     ev_action_t  *action;
     if (port >= NR_EVS) {
         printk("Port number too large: %d\n", port);
-        goto out;
+               goto out;
     }
 
     action = &ev_actions[port];
     action->count++;
 
-    if (!action->handler)
-    {
-        printk("Spurious event on port %d\n", port);
-        goto out;
-    }
-    
-    if (action->status & EVS_DISABLED)
-    {
-        printk("Event on port %d disabled\n", port);
-        goto out;
-    }
-    
     /* call the handler */
-    action->handler(port, regs);
-    
+       action->handler(port, regs, action->data);
+
  out:
        clear_evtchn(port);
+
     return 1;
 
 }
 
-int bind_evtchn( u32 port, void (*handler)(int, struct pt_regs *) )
+int bind_evtchn( u32 port, void (*handler)(int, struct pt_regs *, void *),
+                                void *data )
 {
        if(ev_actions[port].handler != default_handler)
         printk("WARN: Handler for port %d already registered, replacing\n",
                                port);
 
+       ev_actions[port].data = data;
+       wmb();
        ev_actions[port].handler = handler;
-       ev_actions[port].status &= ~EVS_DISABLED;         
+
        /* Finally unmask the port */
        unmask_evtchn(port);
 
@@ -82,13 +82,14 @@ void unbind_evtchn( u32 port )
        if (ev_actions[port].handler == default_handler)
                printk("WARN: No handler for port %d when unbinding\n", port);
        ev_actions[port].handler = default_handler;
-       ev_actions[port].status |= EVS_DISABLED;
+       wmb();
+       ev_actions[port].data = NULL;
 }
 
-int bind_virq( u32 virq, void (*handler)(int, struct pt_regs *) )
+int bind_virq( u32 virq, void (*handler)(int, struct pt_regs *, void *data),
+                          void *data)
 {
        evtchn_op_t op;
-       int ret = 0;
 
        /* Try to bind the virq to a port */
        op.cmd = EVTCHNOP_bind_virq;
@@ -97,13 +98,11 @@ int bind_virq( u32 virq, void (*handler)(int, struct pt_regs *) )
 
        if ( HYPERVISOR_event_channel_op(&op) != 0 )
        {
-               ret = 1;
                printk("Failed to bind virtual IRQ %d\n", virq);
-               goto out;
+               return 1;
     }
-    bind_evtchn(op.u.bind_virq.port, handler); 
-out:
-       return ret;
+    bind_evtchn(op.u.bind_virq.port, handler, data);
+       return 0;
 }
 
 void unbind_virq( u32 port )
@@ -137,13 +136,38 @@ void init_events(void)
 #endif
     /* inintialise event handler */
     for ( i = 0; i < NR_EVS; i++ )
-    {
-        ev_actions[i].status  = EVS_DISABLED;
+       {
         ev_actions[i].handler = default_handler;
         mask_evtchn(i);
     }
 }
 
-void default_handler(int port, struct pt_regs *regs) {
+void default_handler(int port, struct pt_regs *regs, void *ignore)
+{
     printk("[Port %d] - event received\n", port);
 }
+
+/* Unfortunate confusion of terminology: the port is unbound as far
+   as Xen is concerned, but we automatically bind a handler to it
+   from inside mini-os. */
+int evtchn_alloc_unbound(void (*handler)(int, struct pt_regs *regs,
+                                                                                void *data),
+                                                void *data)
+{
+       u32 port;
+       evtchn_op_t op;
+       int err;
+
+       op.cmd = EVTCHNOP_alloc_unbound;
+       op.u.alloc_unbound.dom = DOMID_SELF;
+       op.u.alloc_unbound.remote_dom = 0;
+
+       err = HYPERVISOR_event_channel_op(&op);
+       if (err) {
+               printk("Failed to alloc unbound evtchn: %d.\n", err);
+               return -1;
+       }
+       port = op.u.alloc_unbound.port;
+       bind_evtchn(port, handler, data);
+       return port;
+}
index c4e7c67fd848f5df4ce8ba72ecbba9cb873dc7b2..c1b58c4db08d5d95df8323c82b964f72e1e1205d 100644 (file)
 #include<traps.h>
 #include <xen/event_channel.h>
 
-#define NR_EVS 1024
-
-/* ev handler status */
-#define EVS_INPROGRESS 1       /* Event handler active - do not enter! */
-#define EVS_DISABLED   2       /* Event disabled - do not enter! */
-#define EVS_PENDING        4   /* Event pending - replay on enable */
-#define EVS_REPLAY         8   /* Event has been replayed but not acked yet */
-
-/* this represents a event handler. Chaining or sharing is not allowed */
-typedef struct _ev_action_t {
-       void (*handler)(int, struct pt_regs *);
-    unsigned int status;               /* IRQ status */
-    u32 count;
-} ev_action_t;
-
 /* prototypes */
 int do_event(u32 port, struct pt_regs *regs);
-int bind_virq( u32 virq, void (*handler)(int, struct pt_regs *) );
-int bind_evtchn( u32 virq, void (*handler)(int, struct pt_regs *) );
+int bind_virq( u32 virq, void (*handler)(int, struct pt_regs *, void *data),
+                          void *data);
+int bind_evtchn( u32 virq, void (*handler)(int, struct pt_regs *, void *data),
+                                void *data );
 void unbind_evtchn( u32 port );
 void init_events(void);
 void unbind_virq( u32 port );
+int evtchn_alloc_unbound(void (*handler)(int, struct pt_regs *regs,
+                                                                                void *data),
+                                                void *data);
 
 static inline int notify_remote_via_evtchn(int port)
 {
index 473a05970592bd0db14a39799fcd41cdb7f63480..809c429789c9e90f5c8b0a0cfa879480e00c4d96 100644 (file)
@@ -89,6 +89,7 @@ size_t strlen(const char *s);
 char  *strchr(const char *s, int c);
 char  *strstr(const char *s1, const char *s2);
 char * strcat(char * dest, const char * src);
+char  *strdup(const char *s);
 
 
 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
@@ -98,6 +99,18 @@ struct kvec {
     size_t iov_len;
 };
 
+#define ASSERT(x)                                              \
+do {                                                           \
+       if (!(x)) {                                                \
+               printk("ASSERTION FAILED: %s at %s:%d.\n",             \
+                          # x ,                                           \
+                          __FILE__,                                       \
+                          __LINE__);                                      \
+        BUG();                                                 \
+       }                                                          \
+} while(0)
 
+/* Consistency check as much as possible. */
+void sanity_check(void);
 
 #endif /* _LIB_H_ */
index 1b99f43a4617d39700d155be101741f3cb55f95c..c52ae43a89f79cbd6ae4be8911aea88c39a5dd7a 100644 (file)
@@ -23,6 +23,7 @@
 #include <os.h>
 #include <types.h>
 #include <lib.h>
+#include <xmalloc.h>
 
 int memcmp(const void * cs,const void * ct,size_t count)
 {
@@ -156,4 +157,13 @@ char * strstr(const char * s1,const char * s2)
         return NULL;
 }
 
+char *strdup(const char *x)
+{
+    int l = strlen(x);
+    char *res = malloc(l + 1);
+       if (!res) return NULL;
+    memcpy(res, x, l + 1);
+    return res;
+}
+
 #endif
index 04ea43dc5161c8e1e90bb6cb8bb79a72874b90f6..1df4a26036e344f98d487b3f6dde2809aa59c729 100644 (file)
@@ -215,7 +215,7 @@ void block_domain(u32 millisecs)
 /*
  * Just a dummy 
  */
-static void timer_handler(int ev, struct pt_regs *regs)
+static void timer_handler(int ev, struct pt_regs *regs, void *ign)
 {
     static int i;
 
@@ -233,5 +233,5 @@ static void timer_handler(int ev, struct pt_regs *regs)
 void init_time(void)
 {
     printk("Initialising timer interface\n");
-    bind_virq(VIRQ_TIMER, &timer_handler);
+    bind_virq(VIRQ_TIMER, &timer_handler, NULL);
 }
index bf04bac1ce2a8336f8ca99f9da888e1422e6a1d3..704ba58104d8f6a29b92ca4f14f1984208ae5c5a 100644 (file)
@@ -112,7 +112,7 @@ static void xenbus_thread_func(void *ign)
     }
 }
 
-static void xenbus_evtchn_handler(int port, struct pt_regs *regs)
+static void xenbus_evtchn_handler(int port, struct pt_regs *regs, void *ign)
 {
     wake_up(&xb_waitq);
 }
@@ -174,7 +174,8 @@ void init_xenbus(void)
     create_thread("xenstore", xenbus_thread_func, NULL);
     DEBUG("buf at %p.\n", xenstore_buf);
     err = bind_evtchn(start_info.store_evtchn,
-                     xenbus_evtchn_handler);
+                     xenbus_evtchn_handler,
+              NULL);
     DEBUG("xenbus on irq %d\n", err);
 }